﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProjectPlotagemGrafo
{
    public class SearchGrafo
    {

        #region Propriedades

        private List<PessoaAlunoRM> _listaTodosAlunosRM;

        public SearchGrafo(List<PessoaAlunoRM> pessoaAluno)
        {
            this._listaTodosAlunosRM = pessoaAluno;
        }

        #endregion

        #region MétodosBusca

        public List<PessoaAlunoRM> BuscaIntermedio(string RegistroMatricular)
        {
            if (BuscaRegistroMatricularNaListagem(RegistroMatricular).RegistroMatricular == null)
                throw new Exception("Aluno inexistente");
            List<PessoaAlunoRM> ligacoesAlunosRM = new List<PessoaAlunoRM>();
            List<PessoaAlunoRM> alunosRMIntermediacao = new List<PessoaAlunoRM>();
            List<PessoaAlunoRM> alunoRMComparacao = new List<PessoaAlunoRM>();
            ligacoesAlunosRM.Add(BuscaRegistroMatricularNaListagem(RegistroMatricular));
            for (int indiceControlador = 0; indiceControlador < ligacoesAlunosRM.Count; indiceControlador++)
                for (int indiceControladorSegundoNivel = 0; indiceControladorSegundoNivel < ligacoesAlunosRM[indiceControlador].outrosAlunos.Count; indiceControladorSegundoNivel++)
                    if (!ligacoesAlunosRM.Contains(BuscaRegistroMatricularNaListagem(ligacoesAlunosRM[indiceControlador].outrosAlunos[indiceControladorSegundoNivel])) && BuscaRegistroMatricularNaListagem(ligacoesAlunosRM[indiceControlador].outrosAlunos[indiceControladorSegundoNivel]).RegistroMatricular != null)
                        ligacoesAlunosRM.Add(BuscaRegistroMatricularNaListagem(ligacoesAlunosRM[indiceControlador].outrosAlunos[indiceControladorSegundoNivel]));
            for (int indiceControlador = 1; indiceControlador < ligacoesAlunosRM.Count; indiceControlador++)
            {
                alunoRMComparacao = PreencheListaAlunosRM(RegistroMatricular, ligacoesAlunosRM[indiceControlador].RegistroMatricular);
                if (alunoRMComparacao.Count < ligacoesAlunosRM.Count - 1)
                    alunosRMIntermediacao.Add(ligacoesAlunosRM[indiceControlador]);
            }

            return alunosRMIntermediacao;
        }
        
        public List<PessoaAlunoRM> BuscaSemLigacoes(string RegistroMatricular)
        {
            if (BuscaRegistroMatricularNaListagem(RegistroMatricular).RegistroMatricular != null)
            {
                List<PessoaAlunoRM> listaNovosAlunosRM = new List<PessoaAlunoRM>();
                listaNovosAlunosRM.Add(BuscaRegistroMatricularNaListagem(RegistroMatricular));
                for (int indiceControlador = 0; indiceControlador < listaNovosAlunosRM.Count; indiceControlador++)
                    for (int k = 0; k < listaNovosAlunosRM[indiceControlador].outrosAlunos.Count; k++)
                        if (!listaNovosAlunosRM.Contains(BuscaRegistroMatricularNaListagem(listaNovosAlunosRM[indiceControlador].outrosAlunos[k])) && BuscaRegistroMatricularNaListagem(listaNovosAlunosRM[indiceControlador].outrosAlunos[k]).RegistroMatricular != null)
                            listaNovosAlunosRM.Add(BuscaRegistroMatricularNaListagem(listaNovosAlunosRM[indiceControlador].outrosAlunos[k]));
                List<PessoaAlunoRM> semLigacoes = new List<PessoaAlunoRM>();
                for (int indiceControlador = 0; indiceControlador < _listaTodosAlunosRM.Count; indiceControlador++)
                    if (!listaNovosAlunosRM.Contains(_listaTodosAlunosRM[indiceControlador]))
                        semLigacoes.Add(_listaTodosAlunosRM[indiceControlador]);
                return semLigacoes;
            }
            else
                throw new Exception("RM inválido");
        }

        public List<PessoaAlunoRM> PreencheListaAlunosRM(string RegistroMatricular, string ignorarRMAluno)
        {
            List<PessoaAlunoRM> ligacoesAlunosRM = new List<PessoaAlunoRM>();
            ligacoesAlunosRM.Add(BuscaRegistroMatricularNaListagem(RegistroMatricular));

            for (int indiceControlador = 0; indiceControlador < ligacoesAlunosRM.Count; indiceControlador++)
                for (int indiceControladorSegundoNivel = 0; indiceControladorSegundoNivel < ligacoesAlunosRM[indiceControlador].outrosAlunos.Count; indiceControladorSegundoNivel++)
                    if (!ligacoesAlunosRM.Contains(BuscaRegistroMatricularNaListagem(ligacoesAlunosRM[indiceControlador].outrosAlunos[indiceControladorSegundoNivel])) && BuscaRegistroMatricularNaListagem(ligacoesAlunosRM[indiceControlador].outrosAlunos[indiceControladorSegundoNivel]).RegistroMatricular != null)
                    {
                        ligacoesAlunosRM.Add(BuscaRegistroMatricularNaListagem(ligacoesAlunosRM[indiceControlador].outrosAlunos[indiceControladorSegundoNivel]));
                        if (ligacoesAlunosRM.Last().RegistroMatricular.Equals(ignorarRMAluno))
                            ligacoesAlunosRM.Remove(ligacoesAlunosRM.Last());
                    }
            return ligacoesAlunosRM;
        }

        public List<PessoaAlunoRM> BuscaEmProfundidadeDefinida(string RegistroMatricular, int distanciaLigacao)
        {
            PessoaAlunoRM pessoaAlunoRM = BuscaRegistroMatricularNaListagem(RegistroMatricular);
            List<PessoaAlunoRM> alunosRMComLigacoes = new List<PessoaAlunoRM>();
            int novoAlunoRM = 0;
            alunosRMComLigacoes.Add(pessoaAlunoRM);
            for (int indiceControlador = 0; indiceControlador < alunosRMComLigacoes.Count; indiceControlador++)
            {
                for (int indiceControladorSegundoNivel = 0; indiceControladorSegundoNivel < alunosRMComLigacoes[indiceControlador].outrosAlunos.Count; indiceControladorSegundoNivel++)
                    if (!alunosRMComLigacoes.Contains(BuscaRegistroMatricularNaListagem(alunosRMComLigacoes[indiceControlador].outrosAlunos[indiceControladorSegundoNivel])) &&
                        BuscaRegistroMatricularNaListagem(alunosRMComLigacoes[indiceControlador].outrosAlunos[indiceControladorSegundoNivel]).RegistroMatricular != null)
                        alunosRMComLigacoes.Add(BuscaRegistroMatricularNaListagem(alunosRMComLigacoes[indiceControlador].outrosAlunos[indiceControladorSegundoNivel]));
                if (novoAlunoRM == indiceControlador)
                {
                    novoAlunoRM = alunosRMComLigacoes.Count - 1;
                    distanciaLigacao--;
                }
                if (distanciaLigacao == 0)
                    break;
            }
            return alunosRMComLigacoes;
        }

        public PessoaAlunoRM BuscaRegistroMatricularNaListagem(string RegistroMatricular)
        {
            PessoaAlunoRM respostaMetodo = new PessoaAlunoRM();
            for (int indiceControlador = 0; indiceControlador < _listaTodosAlunosRM.Count; indiceControlador++)
                if (_listaTodosAlunosRM[indiceControlador].RegistroMatricular.Equals(RegistroMatricular))
                    respostaMetodo = _listaTodosAlunosRM[indiceControlador];
            return respostaMetodo;
        }

        public List<PessoaAlunoRM> BuscaDistanciaDeMenorIntervalo(string registroMatricularPartida, string registroMatricularChegada)
        {
            PessoaAlunoRM chegadaNode = BuscaRegistroMatricularNaListagem(registroMatricularChegada);
            PessoaAlunoRM partidaNode = BuscaRegistroMatricularNaListagem(registroMatricularPartida);
            if (partidaNode.RegistroMatricular == null || chegadaNode.RegistroMatricular == null)
                throw new Exception("RM de partida ou chegada Inválido");
            else
            {
                int nodeIntermedio = 0;
                List<PessoaAlunoRM> listaNovosAlunosRM = new List<PessoaAlunoRM>();
                List<int> posicionamentoListagem = new List<int>();
                listaNovosAlunosRM.Add(partidaNode);
                int novoAlunoRM = 0;
                posicionamentoListagem.Add(novoAlunoRM);
                for (int indiceControlador = 0; indiceControlador < listaNovosAlunosRM.Count; indiceControlador++)
                {
                    for (int k = 0; k < listaNovosAlunosRM[indiceControlador].outrosAlunos.Count; k++)
                    {
                        if (listaNovosAlunosRM[indiceControlador].outrosAlunos[k] == registroMatricularChegada)
                        {
                            listaNovosAlunosRM.Add(BuscaRegistroMatricularNaListagem(listaNovosAlunosRM[indiceControlador].outrosAlunos[k]));
                            indiceControlador = listaNovosAlunosRM.Count;
                            break;
                        }
                        else if (!listaNovosAlunosRM.Contains(BuscaRegistroMatricularNaListagem(listaNovosAlunosRM[indiceControlador].outrosAlunos[k])))
                        {
                            if (BuscaRegistroMatricularNaListagem(listaNovosAlunosRM[indiceControlador].outrosAlunos[k]).RegistroMatricular != null)
                                listaNovosAlunosRM.Add(BuscaRegistroMatricularNaListagem(listaNovosAlunosRM[indiceControlador].outrosAlunos[k]));
                        }
                    }

                    if (novoAlunoRM == indiceControlador)
                    {
                        novoAlunoRM = listaNovosAlunosRM.Count - 1;
                        nodeIntermedio++;
                        posicionamentoListagem.Add(novoAlunoRM);
                    }
                }

                if (!listaNovosAlunosRM.Contains(chegadaNode))
                {
                    return null;
                }

                List<PessoaAlunoRM> Mostrar = new List<PessoaAlunoRM>();
                Mostrar.Add(chegadaNode);
                for (int i = posicionamentoListagem.Last(); i >= 0; i--)
                {
                    if (listaNovosAlunosRM[i].outrosAlunos.Contains(chegadaNode.RegistroMatricular))
                    {
                        Mostrar.Add(listaNovosAlunosRM[i]);
                        chegadaNode = listaNovosAlunosRM[i];
                        posicionamentoListagem.Remove(posicionamentoListagem.Last());
                        if (posicionamentoListagem.Count == 0)
                        {
                            i = 0;
                        }
                        else
                        {
                            i = posicionamentoListagem.Last() + 1;
                        }
                    }
                }

                return Mostrar;
            }
        }

        #endregion

    }
}
